function [SmoothedTrainTVs, SmoothedTestTVs] = tdasr_articToSmoothTV(TrainData, TestData, func, pc, means)
% tdasr_smoothData
%
%    take TrainData and TestData, apply the transforms to TV space, 
%    smooth those trajectories, and output the data
%
%    lowpass below 20Hz for articulators (see Hogden:2007:Inverting who cite
%    Muller and McLeod, 1982; Nelson, 1977)

global T_TorgoParams
global PhoneCode;
global art_x;
global art_y;
global tv_i

SmoothedTrainTVs = cell(0);
SmoothedTestTVs  = cell(0);

[b,a] = butter(9,20/8000);    % cutoff at 20Hz, assuming 16000 sample rate

for t=1:size(TrainData.MOCHA.artic,2)

  newArtic = zeros(size(TrainData.MOCHA.artic{t}));
  phoneData = TrainData.MOCHA.phone{t};
  articData = TrainData.MOCHA.artic{t};
  % VEL
  vData = [articData(art_x.V,:)' articData(art_y.V,:)'];
  vData(:,1) = vData(:,1) - means.VEL(1);
  vData(:,2) = vData(:,2) - means.VEL(2);
  vData = vData*pc.VEL(:,1);
  newArtic(tv_i.iVEL,:) = func.VEL( vData )';
  % LTH
  vData = [articData(art_x.LI,:)' articData(art_y.LI,:)'];
  vData(:,1) = vData(:,1) - means.LTH(1);
  vData(:,2) = vData(:,2) - means.LTH(2);
  vData = vData*pc.LTH(:,1);
  newArtic(tv_i.iLTH,:) = func.LTH( vData )';
  % LA
  laX = articData(art_x.UL,:) - articData(art_x.LL,:);
  laY = articData(art_y.UL,:) - articData(art_y.LL,:);
  laX = laX.^2;
  laY = laY.^2;
  dist = laX + laY;
  dist = sqrt(dist);
  dist = dist - means.LA;
  newArtic(tv_i.iLA,:) = func.LA( dist );
  % LP
  LPdataX = mean([articData(art_x.UL,:)' articData(art_x.LL,:)'],2);
  LPdataY = mean([articData(art_y.UL,:)' articData(art_y.LL,:)'],2);
  LPdata = ([LPdataX LPdataY]- repmat(means.LP, size(LPdataX,1),1))*pc.LP;
  newArtic(tv_i.iLP,:) = func.LP( LPdata(:,2) )';
  % LD
  laX = articData(art_x.UI,:) - articData(art_x.LL,:);
  laY = articData(art_y.UI,:) - articData(art_y.LL,:);
  laX = laX.^2;
  laY = laY.^2;
  dist = laX + laY;
  dist = sqrt(dist);
  dist = dist - means.LD;
  newArtic(tv_i.iLD,:) = func.LD( dist );
  % TT
  vdata      = [articData(art_x.TT,:)' articData(art_y.TT,:)'];
  vdata      = (vdata-repmat(means.TT,size(vdata,1),1))*pc.TT;
  newArtic(tv_i.iTTCL,:) = func.TTCL( vdata(:,1) )';
  newArtic(tv_i.iTTCD,:) = func.TTCD( vdata(:,2) )';
  % TD
  vdata      = [articData(art_x.TD,:)' articData(art_y.TD,:)'];
  vdata      = (vdata-repmat(means.TD,size(vdata,1),1))*pc.TD;
  newArtic(tv_i.iTDCL,:) = func.TDCL( vdata(:,1) )';
  newArtic(tv_i.iTDCD,:) = func.TDCD( vdata(:,2) )';
  % GLO 
  mask = (phoneData == PhoneCode.a | phoneData == PhoneCode.iX | phoneData == PhoneCode.jh | phoneData == PhoneCode.d | ...
          phoneData == PhoneCode.y | phoneData == PhoneCode.u | phoneData == PhoneCode.iy | phoneData == PhoneCode.g | ...
          phoneData == PhoneCode.aa | phoneData == PhoneCode.e |phoneData == PhoneCode.v |phoneData == PhoneCode.XX | ...
          phoneData == PhoneCode.uu | phoneData == PhoneCode.oo | phoneData == PhoneCode.b | phoneData == PhoneCode.z | ...
          phoneData == PhoneCode.oi | phoneData == PhoneCode.ow | phoneData == PhoneCode.w | phoneData == PhoneCode.r | ...
          phoneData == PhoneCode.ei | phoneData == PhoneCode.ii | phoneData == PhoneCode.dh | phoneData == PhoneCode.X | ...
          phoneData == PhoneCode.i | phoneData == PhoneCode.ou | phoneData == PhoneCode.n | phoneData == PhoneCode.zh | ...
          phoneData == PhoneCode.m | phoneData == PhoneCode.eir | phoneData == PhoneCode.l | phoneData == PhoneCode.uh |...
          phoneData == PhoneCode.ng | phoneData == PhoneCode.ai | phoneData == PhoneCode.o);
  newArtic(tv_i.iGLO,:) = double(mask);

  % median filter, order 3
  newArtic = medfilt1(newArtic,3,[],2);
  %% if signal processing toolbox is not available
  %% Apply the median filter of size 5 to signal x
  %y = zeros(size(x)); % Preallocate
  %for k = 3:length(x)−2
  %  tmp = sort(x(k−2:k+2));
  %  y(k) = tmp(3); % y(k) = median(x(k−2:k+2));
  %end

  % butterworth filter cutoff=20Hz
  for tv=1:size(newArtic,1)
    newArtic(tv,:) = filter(b,a,newArtic(tv,:));
  end
  SmoothedTrainTVs{t} = newArtic;
end

% =======================================================================================
% Test data
for t=1:size(TestData.MOCHA.artic,2)
  newArtic = zeros(size(TestData.MOCHA.artic{t}));
  phoneData = TestData.MOCHA.phone{t};
  articData = TestData.MOCHA.artic{t};
  % VEL
  vData = [articData(art_x.V,:)' articData(art_y.V,:)'];
  vData(:,1) = vData(:,1) - means.VEL(1);
  vData(:,2) = vData(:,2) - means.VEL(2);
  vData = vData*pc.VEL(:,1);
  newArtic(tv_i.iVEL,:) = func.VEL( vData )';
  % LTH
  vData = [articData(art_x.LI,:)' articData(art_y.LI,:)'];
  vData(:,1) = vData(:,1) - means.LTH(1);
  vData(:,2) = vData(:,2) - means.LTH(2);
  vData = vData*pc.LTH(:,1);
  newArtic(tv_i.iLTH,:) = func.LTH( vData )';
  % LA
  laX = articData(art_x.UL,:) - articData(art_x.LL,:);
  laY = articData(art_y.UL,:) - articData(art_y.LL,:);
  laX = laX.^2;
  laY = laY.^2;
  dist = laX + laY;
  dist = sqrt(dist);
  dist = dist - means.LA;
  newArtic(tv_i.iLA,:) = func.LA( dist );
  % LP
  LPdataX = mean([articData(art_x.UL,:)' articData(art_x.LL,:)'],2);
  LPdataY = mean([articData(art_y.UL,:)' articData(art_y.LL,:)'],2);
  LPdata = ([LPdataX LPdataY]- repmat(means.LP, size(LPdataX,1),1))*pc.LP;
  newArtic(tv_i.iLP,:) = func.LP( LPdata(:,2) )';
  % LD
  laX = articData(art_x.UI,:) - articData(art_x.LL,:);
  laY = articData(art_y.UI,:) - articData(art_y.LL,:);
  laX = laX.^2;
  laY = laY.^2;
  dist = laX + laY;
  dist = sqrt(dist);
  dist = dist - means.LD;
  newArtic(tv_i.iLD,:) = func.LD( dist );
  % TT
  vdata      = [articData(art_x.TT,:)' articData(art_y.TT,:)'];
  vdata      = (vdata-repmat(means.TT,size(vdata,1),1))*pc.TT;
  newArtic(tv_i.iTTCL,:) = func.TTCL( vdata(:,1) )';
  newArtic(tv_i.iTTCD,:) = func.TTCD( vdata(:,2) )';
  % TD
  vdata      = [articData(art_x.TD,:)' articData(art_y.TD,:)'];
  vdata      = (vdata-repmat(means.TD,size(vdata,1),1))*pc.TD;
  newArtic(tv_i.iTDCL,:) = func.TDCL( vdata(:,1) )';
  newArtic(tv_i.iTDCD,:) = func.TDCD( vdata(:,2) )';
  % GLO 
  mask = (phoneData == PhoneCode.a | phoneData == PhoneCode.iX | phoneData == PhoneCode.jh | phoneData == PhoneCode.d | ...
          phoneData == PhoneCode.y | phoneData == PhoneCode.u | phoneData == PhoneCode.iy | phoneData == PhoneCode.g | ...
          phoneData == PhoneCode.aa | phoneData == PhoneCode.e |phoneData == PhoneCode.v |phoneData == PhoneCode.XX | ...
          phoneData == PhoneCode.uu | phoneData == PhoneCode.oo | phoneData == PhoneCode.b | phoneData == PhoneCode.z | ...
          phoneData == PhoneCode.oi | phoneData == PhoneCode.ow | phoneData == PhoneCode.w | phoneData == PhoneCode.r | ...
          phoneData == PhoneCode.ei | phoneData == PhoneCode.ii | phoneData == PhoneCode.dh | phoneData == PhoneCode.X | ...
          phoneData == PhoneCode.i | phoneData == PhoneCode.ou | phoneData == PhoneCode.n | phoneData == PhoneCode.zh | ...
          phoneData == PhoneCode.m | phoneData == PhoneCode.eir | phoneData == PhoneCode.l | phoneData == PhoneCode.uh |...
          phoneData == PhoneCode.ng | phoneData == PhoneCode.ai | phoneData == PhoneCode.o);
  newArtic(tv_i.iGLO,:) = double(mask);

  % median filter, order 3
  newArtic = medfilt1(newArtic,3,[],2);
  for tv=1:size(newArtic,1)
    newArtic(tv,:) = filter(b,a,newArtic(tv,:));
  end
  SmoothedTestTVs{t} = newArtic;
end

return